#pragma once
#include "MysqlDao.hpp"
#include "Singleton.hpp"
#include "const.hpp"
#include "message.grpc.pb.h"
#include "message.pb.h"
#include <atomic>
#include <condition_variable>
#include <cstddef>
#include <grpcpp/channel.h>
#include <grpcpp/client_context.h>
#include <grpcpp/grpcpp.h>
#include <grpcpp/support/status.h>
#include <json/json.h>
#include <json/value.h>
#include <memory>
#include <queue>
#include <string>
#include <unordered_map>

using grpc::Channel;
using grpc::ClientContext;
using grpc::Status;

using message::AddFriendReq;
using message::AddFriendRsp;

using message::AuthFriendReq;
using message::AuthFriendRsp;

using message::ChatService;
using message::GetChatServerReq;
using message::LoginReq;
using message::LoginRsp;

using message::TextChatMsgReq;
using message::TextChatMsgRsp;

class ChatConPool {
private:
  size_t _poolSize;
  std::string _host;
  std::string _port;
  std::atomic<bool> _stop;
  std::queue<std::unique_ptr<ChatService::Stub>> _connections;
  std::mutex _mutex;
  std::condition_variable _cond;

private:
  void close();

public:
  ChatConPool(size_t poolSize, std::string host, std::string port);
  ~ChatConPool();
  std::unique_ptr<ChatService::Stub> getConnection();
  void returnConnection(std::unique_ptr<ChatService::Stub> con);
};

class ChatGrpcClient : public Singleton<ChatGrpcClient> {
  friend class Singleton<ChatGrpcClient>;

private:
  std::unordered_map<std::string, std::unique_ptr<ChatConPool>> _pools;

private:
  ChatGrpcClient();

public:
  ~ChatGrpcClient() = default;
  AddFriendRsp NotifyAddFriend(std::string serverIp, const AddFriendReq);
  AuthFriendRsp NotifyAuthFriend(std::string serverIp, const AuthFriendReq);
  bool GetBaseInfo(std::string baseKey, int uid,
                   std::shared_ptr<UserInfo> &userInfo);
  TextChatMsgRsp NotifyTextChatMsg(std::string serverIp, const TextChatMsgReq);
};